package org.example.core;

import org.example.constant.constant;
import org.example.util.FileUtil;
import org.example.util.HttpUtil;
import org.example.util.LogUtil;

import java.io.*;
import java.net.HttpURLConnection;
import java.util.ArrayList;
import java.util.concurrent.*;

public class Downloader {

    public ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1);

    //创建线程池对象
    public ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(constant.THREAD_NUM,constant.THREAD_NUM,0,TimeUnit.SECONDS,new ArrayBlockingQueue<>(constant.THREAD_NUM));

    private CountDownLatch countDownLatch = new CountDownLatch(constant.THREAD_NUM);

    public void downloader(String url) {

        //获取文件名
        String httpFileName = HttpUtil.getHttpFileName(url);
        System.out.println("该链接下载的文件名称是：" + httpFileName);

        //文件路径
        httpFileName = constant.PATH + httpFileName;
        System.out.println("文件的存放路径是：" + httpFileName);
        //System.out.println(httpFileName + url);


        //获取本地文件大小
        long localFileLength = FileUtil.getFileContentLength(httpFileName);
        System.out.println("本地文件的大小:" + FileUtil.getFileContentLength(httpFileName));

        HttpURLConnection httpURLConnection = null;
        DownloaderInfoThread dit = null;
        try {
            httpURLConnection = HttpUtil.getHttpURLConnection(url);

            //获取下载文件总大小
            int contentLength = httpURLConnection.getContentLength();
            //判断文件是否下载过
            if (localFileLength >= contentLength) {
                LogUtil.info("()已经下载完毕，无须重复下载！", httpFileName);
                return;
            }


            //创建下载信息任务对象
            dit = new DownloaderInfoThread(contentLength);
            //将任务交给线程执行，每隔一秒执行一次
            scheduledExecutorService.scheduleAtFixedRate(dit, 1, 1, TimeUnit.SECONDS);

            //切分任务
            ArrayList<Future> arrayList = new ArrayList<>();
            spilt(url,arrayList);

//            arrayList.forEach( future -> {
//                try {
//                    future.get();
//                } catch (InterruptedException e) {
//                    e.printStackTrace();
//                } catch (ExecutionException e) {
//                    e.printStackTrace();
//                }
//            } );

            countDownLatch.wait();


            //合并文件
            if (merge(httpFileName)){
                //清除临时文件
                clearTemp(httpFileName);
            }


        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        }

//        try (
//             InputStream input = httpURLConnection.getInputStream();
//             BufferedInputStream bis= new BufferedInputStream(input);
//             FileOutputStream fos= new FileOutputStream(httpFileName);
//             BufferedOutputStream bos = new BufferedOutputStream(fos);
//        ){
//            int len = -1;
//            byte[] buffer = new byte[constant.BYTE_SIZE];
//            while ((len = bis.read(buffer))  != -1){
//                dit.downSize += len;
//                bos.write(buffer,0,len);
//            }
//        } catch (FileNotFoundException e) {
//            //System.out.println("下载文件不存在!");
//            LogUtil.error("下载文件()不存在!               ",httpFileName);
//        }catch (Exception e ){
//            //System.out.println("下文文件失败!");
//            LogUtil.error("下载文件()失败！");
//        }finally {



        finally{

            System.out.print("\r");
            System.out.print(httpFileName + "下载完成");
            //LogUtil.info("文件()下载完成",httpFileName);

            if (httpURLConnection != null){
                httpURLConnection.disconnect();
            }

            //关闭线程任务
            scheduledExecutorService.shutdownNow();
            //关闭线程池
            threadPoolExecutor.shutdown();
        }
    }

    //文件切分下载
    public void spilt(String url, ArrayList<Future> futureArrayList){


        try {
            //计算下载文件大小
            long contentLength  = HttpUtil.getHttpFileContentLength(url);

            //计算切分后文件大小
            long size = contentLength / constant.THREAD_NUM;
            //计算分块个数
            for (int i  = 0 ; i < constant.THREAD_NUM; i++){
                //计算下载起始位置
                long startPos = i * size;
                //计算结束位置
                long endPos;

                if(i == constant.THREAD_NUM - 1){
                    //下载的最后一块,剩余的部分
                    endPos = 0;
                }else {
                    endPos = startPos + size;
                }

                if (startPos !=  0){
                    startPos ++;
                }

                //创建任务对象
                DownloaderTask downloaderTask = new DownloaderTask(url,startPos,endPos,i,countDownLatch);
                //将任务提交到线程池中
                Future<Boolean> future = threadPoolExecutor.submit(downloaderTask);
                futureArrayList.add(future);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //文件合并方法
    public boolean merge(String fileName){

        LogUtil.info("开始文件合并()",  fileName);
        byte[]  buffer  = new byte[constant.BYTE_SIZE];
        int len = -1;
        try(RandomAccessFile raf = new RandomAccessFile(fileName,"rw")){

            for (int i = 0; i < constant.THREAD_NUM ; i++) {
                try(BufferedInputStream bis = new BufferedInputStream(new FileInputStream(fileName + ".temp" + i))){
                    while ((len = bis.read(buffer))  != -1){
                        raf.write(buffer , 0 , len);
                    }
                }

            }
            LogUtil.info("文件合并完毕()",fileName);
        }catch (Exception e){
            e.printStackTrace();
            return false;
        }

        return true;
    }

    //清除临时文件
    public boolean clearTemp(String fileName){

        for (int i = 0; i < constant.THREAD_NUM; i++) {
            File file = new File(fileName + ".temp" + i);
            file.delete();
        }

        return true;
    }
}
